<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>原型|继承</title>
    <script>
        //JS一切皆对象吗？  两大类：原始值 + 对象
        //对象有区别  函数对象 和 普通对象
        //函数对象： new Function
        //函数实例：属于普通对象
        function f(){} // f fuction
        var f1 = new f();
        //f1 --> object
        /**************/
        //每一个函数对象都有一个prototype;普通对象没有
        //var f = new Function(); == function f (){}
        //var o = new Ojbect();   == o = {};
        //constructor
        //prototype 下面有 constructor 属性，指向函数

        function Person(){};
        Person.prototype.name = 'Hanley';
        Person.prototype.age=20;
        var person1 = new Person();
        var person2 = new Person();
        console.log(person1.name);

        var cat1 = {};
        cat1.name = "我的猫";
        cat1.color = "白色";
        var cat2 = {};
        cat2.name = "你的猫";
        cat2.color = "黑色";
        //如果有N只猫，上面的方式不方便

        //构造一个原型,普通函数原型
        function cat(name,color){//普通函数
            return {
                name:name,
                color:color
            }
        };
        var cat01 = cat("MyCat","white");
        var cat02 = cat("YourCat","black")
        console.log(cat02.name)


        //构造函数原型
        function Cat(name,color){//构造函数,首字母大写(驼峰命名)
            this.name  = name;
            this.color = color;
            this.type  = "动物";
            this.eat = function(){console.log("吃老鼠")};
        };
        var cat03 = new Cat("MyCat","white");
        var cat04 = new Cat("YourCat","black")
        console.log(cat03.name)
        console.log(cat03.eat());

        //构造函数 + prototype
        function CatDemo(name,color){//构造函数
            this.name  = name;
            this.color = color;
        };
        CatDemo.prototype.type = "动物";
        CatDemo.prototype.eat = function(){console.log("吃老鼠la")};
        var cat05 = new CatDemo("MyCat","white");
        var cat06 = new CatDemo("YourCat","black")
        console.log(cat05.type);
        console.log(cat05.eat());

        //prototype 验证
        //in 不管自身属性还是原型属性都返回true
        console.log('name' in cat05);//true
        console.log('type' in cat05);//true
        //hasOwnProperty 自身的属性为true,原型属性为false
        console.log(cat05.hasOwnProperty('name'));//true
        console.log(cat05.hasOwnProperty('type'));//false

        //构造函数的继承
        function Animal() {
            this.type = "动物";
        };
        function CatE(name,color) {
            Animal.apply(this);//将父对象的构造函数绑定在子对象上
            this.name = name;
            this.color = color;
        };
        var cat07 = new CatE("X猫x","x百色x");
        console.log(cat07.type);
        //apply() call() 在一个对象中调用另一个对象
        //apply(this,参数)
        //区别：参数不同. apply 传数组； call 一个一个传
        
        //call & apply 使用示例
        function Catx(name,color){
            this.name = name;
            this.color = color;
        }
        var catx = new Catx();
        var ox = {};
        //Catx.apply(ox,['x丁当猫','x花色']);
        Catx.call(ox,'x丁当猫','x花色');
        console.log('apply|call 使用-'+ox.name);


        //prototype
        function CatF(name,color) {
            this.name = name;
            this.color = color;
        };
        CatF.prototype = new Animal();
        var cat08 = new CatF('F猫','花色');
        console.log(cat08.type);


        function AnimalB(){};
        AnimalB.prototype.type = '动物~';
        function CatB(name,color){
            this.name = name;
            this.color = color;
        };
        //这种方式内存更优。缺点Cat.prototype和Animal.prototype 指向了同一个对象
        CatB.prototype = AnimalB.prototype;
        var cat09 = new CatB('哈猫','blue');
        console.log(cat09.type);


    </script>
</head>
<body>
    
</body>
</html>